
package mytomcat.filter;

import mytomcat.MyTomcat;
import mytomcat.anno.Servlet;
import mytomcat.constant.FilterConstant;
import mytomcat.core.MyRequest;
import mytomcat.core.MyResponse;
import mytomcat.dto.ServletInfo;
import mytomcat.dto.SourceInfo;
import mytomcat.dto.XmlNodeInfo;
import mytomcat.filter.base.BaseFilter;
import mytomcat.servlet.ErrorServlet;
import mytomcat.servlet.base.MyServlet;
import mytomcat.servlet.source.SourceDefaultServlet;
import mytomcat.util.PackageUtil;
import mytomcat.util.StringUtil;
import mytomcat.util.XmlNodeUtil;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <ul>
 * <li>Title: -MyFilter</li>
 * <li>Description: TODO </li>
 * <li>Copyright: Copyright (c) 2018</li>
 * <li>Company: /</li>
 * </ul>
 *
 * @author swc
 * @version V1.0
 * @date 2020/5/29 0029 上午 9:54
 */
public class MyFilter implements BaseFilter {

    /**
     * 功能描述: 获取servlet的信息
     * @param xmlNodeInfo
     * @return: java.util.Map<java.lang.String,java.lang.String>
     * @author: swc
     * @date: 2020/5/29 0029 下午 16:03
    */
    public Map<String, ServletInfo> getSerVletInfo(XmlNodeInfo xmlNodeInfo) {
//      //拦截器-servelet url
        XmlNodeInfo filterUrl = XmlNodeUtil.getValue(xmlNodeInfo.getAllNode(),FilterConstant.FILTERBEAN,FilterConstant.FILTERURLSUFFIX,0);
        String filterUrls = filterUrl.getValue();

//      //拦截器-servelet扫描包信息
        XmlNodeInfo scanPack = XmlNodeUtil.getValue(xmlNodeInfo.getAllNode(),FilterConstant.FILTERBEAN, FilterConstant.FILTERSCANPACK, 0);
        String scanPacks = scanPack.getValue();

//      //视图前缀
        XmlNodeInfo webviewPrefix = XmlNodeUtil.getValue(xmlNodeInfo.getAllNode(),"webView", FilterConstant.WEBVIEPREFIX, 0);
        String viewPrefix = webviewPrefix.getValue();

//      //视图后缀
        XmlNodeInfo webviewSuffix = XmlNodeUtil.getValue(xmlNodeInfo.getAllNode(),"webView", FilterConstant.WEBVIEWSUFFIX, 0);
        String viewSuffix = webviewSuffix.getValue();

        //扫描当前包下面的类
        List<String> className = PackageUtil.getClassName(scanPacks.replaceAll("\\*",""), false);

        //servelet的映射
        Map<String, ServletInfo> urlServletMap = new HashMap<String, ServletInfo>();
//                MyTomcat.urlServletMap;

        ServletInfo servletInfo =null;
        for(String classN:className){
            try {
                servletInfo = new ServletInfo();
                Class aClass = Class.forName(classN);
                Servlet servlet = (Servlet)aClass.getAnnotation(Servlet.class);

                //生成默认的url 以serlvet类名命名 去掉Servlet 前面加上"/"
                String  url= "".equals(servlet.url())||servlet.url()==null?
                        aClass.getSimpleName().replace("Servlet",""):servlet.url();

                String  viewName= "".equals(servlet.path())||servlet.path()==null?
                        aClass.getSimpleName().replace("Servlet","").toLowerCase()
                        :servlet.path();

                url =StringUtil.lowerFirstWord(url);

                url = url.startsWith("/")?url:"/"+url;

                servletInfo.setClassName(classN);
                servletInfo.setUrl(url);
                servletInfo.setViewName(viewName);
                servletInfo.setViewPrefix(viewPrefix);
                servletInfo.setViewSuffix(viewSuffix);

                //加上反斜杠
                urlServletMap.put(url,servletInfo);

            }catch (Exception ex){
                 ex.printStackTrace();
            }

        }

        return urlServletMap;
    }


    /**
     * 功能描述: 拦截相关url 是否放行  不匹配的非空url进入错误页面
     * @param myRequest
     * @param myResponse
     * @param xmlNodeInfo
     * @return: void
     * @author: swc
     * @date: 2020/5/29 0029 下午 16:03
    */
    public void filterAllowUrl(MyRequest myRequest, MyResponse myResponse, XmlNodeInfo xmlNodeInfo) {
//      //拦截器-方向的url[后缀为.jsp .html]
        XmlNodeInfo filterUrl = XmlNodeUtil.getValue(xmlNodeInfo.getAllNode(),FilterConstant.FILTERBEAN ,FilterConstant.FILTERURLSUFFIX, 0);
        String filterUrls = filterUrl.getValue();

        //静态资源
        SourceInfo sourceInfo = MyTomcat.sourceInfo;

        if(myRequest.getUrl()!=null && !"".equals(myRequest.getUrl())){
            if(!isSource(myRequest,myResponse,sourceInfo)){
                //请求分发
                System.out.println("当前请求url:"+myRequest.getUrl()+"\n");
                dispatch(myRequest,myResponse,filterUrls);
            }

        }

    }

    /**
     * 功能描述: 是否静态资源
     * @param myRequest
     * @param myResponse
     * @param sourceInfo
     * @return: boolean
     * @author: swc
     * @date: 2020/6/2 0002 上午 10:17
    */
    private boolean isSource(MyRequest myRequest, MyResponse myResponse, SourceInfo sourceInfo) {
        List<String> realPath = sourceInfo.getRealPath();
        String path ="";
        for(String str:realPath ){
            if(myRequest.getUrl().contains(str.replace("*",""))){
                path =myRequest.getUrl();
            }
        }
        if("".equals(path)){
            return false;
        }
        //属于静态资源 进行处理
        try {
            String servletClass = sourceInfo.getServletClass();
            Class<?> aClass = Class.forName(servletClass);
            SourceDefaultServlet defaultServlet = (SourceDefaultServlet)aClass.newInstance();
            ServletInfo servletInfo =new ServletInfo();
            servletInfo.setViewPrefix("/webapp/");
            servletInfo.setViewSuffix("");

            int indexLocal = path.indexOf("?");
            indexLocal =indexLocal>=0?indexLocal:path.length();
            servletInfo.setViewName(path.substring(0,indexLocal));

            if(path.contains(".css")){
                servletInfo.setContentType("text/css");
            }
            else if(path.contains(".js")){
                servletInfo.setContentType("application/javascript");
            }
            else if(path.contains(".ico")){
                servletInfo.setContentType("image/x-icon");
            }else{
                servletInfo.setContentType("other*");
            }
            System.out.println("加载资源路径:"+myRequest.getUrl());
            defaultServlet.doGet(myRequest,myResponse,servletInfo);
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return true;
    }

    /**
     * 功能描述: 请求分发给相应的servlet 处理
     * @param myRequest
     * @param myResponse
     * @param filterUrls
     * @return: void
     * @author: swc
     * @date: 2020/5/29 0029 下午 16:06
    */
    public static void dispatch(MyRequest myRequest, MyResponse myResponse,String filterUrls) {
        Map<String, ServletInfo> urlServletMap = MyTomcat.urlServletMap;
        String url =myRequest.getUrl();

        //去除请求地址的参数
        Pattern compile = Pattern.compile(filterUrls.replaceAll("\\,","|")+"[?](\\w|\\d)?");
        Matcher matcher = compile.matcher(url);

        if(matcher.find()){
            url = url.substring(0,url.indexOf(matcher.group()));
        }

        ServletInfo servletInfo = urlServletMap.get(url);
        String clazz =null;

        //反射
        try {
            //错误
            if(servletInfo==null){
                clazz ="mytomcat.servlet.ErrorServlet";
                Class<ErrorServlet> errorServletClass = ErrorServlet.class;
                Servlet annotation = errorServletClass.getAnnotation(Servlet.class);

                String urlInfo = annotation.url()==null||"".equals(annotation.url().trim())?
                        errorServletClass.getSimpleName().replace("Servlet",""):annotation.url();

                urlInfo =StringUtil.lowerFirstWord(urlInfo);
                urlInfo = urlInfo.startsWith("/")?urlInfo:"/"+urlInfo;

                servletInfo = urlServletMap.get(urlInfo);
            }else{
                clazz = servletInfo.getClassName();
            }

            Class aClass = Class.forName(clazz);

            Class<MyServlet> myServletClass = (Class<MyServlet>)aClass;
            MyServlet myServlet= myServletClass.newInstance();
            myServlet.service(myRequest,myResponse,servletInfo);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }


}
